package com.photobook
{
    import flash.geom.*;
    import flash.utils.*;

    public class GIFDecoder extends Object
    {
        private var delay:Number;
        private var transIndex:Number;
        private var bgIndex:Number;
        private var act:Array;
        private var gct:Array;
        private var header:ByteArray;
        private var imageByteArrays:Array;
        public var bgColor:int;
        public var height:Number;
        private var gctFlag:Boolean;
        private var bitmaps:Array;
        public var rectBounds:Array;
        private var _isGif:Boolean = false;
        private var gctSize:Number;
        public var width:Number;
        private var loopCount:Number;
        private var graphicsByteArrays:Array;
        private var applicationExtension:ByteArray;
        public var delays:Array;
        private var transparency:Boolean;
        private var lct:Array;
        public var transparentColors:Array;
        private var lctFlag:Boolean;
        private var bytes:ByteArray;
        public var disposals:Array;
        private var interlace:Boolean;
        private var comments:Array;
        private var lctSize:Number;

        public function GIFDecoder(param1:ByteArray) : void
        {
            _isGif = false;
            imageByteArrays = new Array();
            graphicsByteArrays = new Array();
            transparentColors = new Array();
            rectBounds = new Array();
            disposals = new Array();
            delays = new Array();
            bitmaps = new Array();
            comments = new Array();
            this.bytes = param1;
            this.bytes.endian = "littleEndian";
            this._isGif = readMagicString(this.bytes);
            return;
        }

        public function getImageByteArray(param1:Number) : ByteArray
        {
            return makeImageData(this.imageByteArrays[param1] as ByteArray, this.graphicsByteArrays[param1] as ByteArray);
        }

        private function readBlock(param1:ByteArray) : ByteArray
        {
            var _loc_2:int;
            var _loc_3:ByteArray;
            _loc_2 = param1.readUnsignedByte();
            _loc_3 = new ByteArray();
            param1.readBytes(_loc_3, 0, _loc_2);
            return _loc_3;
        }

        private function readMagicString(param1:ByteArray) : Boolean
        {
            var _loc_2:String;
            param1.position = 0;
            _loc_2 = param1.readUTFBytes(6);
            return _loc_2.indexOf("GIF") == 0;
        }

        public function get numImages() : Number
        {
            return imageByteArrays.length;
        }

        private function readGraphicControlExt(param1:ByteArray) : ByteArray
        {
            var _loc_2:Number;
            var _loc_3:int;
            var _loc_4:int;
            var _loc_5:Boolean;
            var _loc_6:Boolean;
            var _loc_7:Number;
            var _loc_8:Number;
            var _loc_9:ByteArray;
            _loc_2 = param1.position;
            param1.readByte();
            _loc_3 = param1.readByte();
            _loc_4 = (_loc_3 & 28) >> 2;
            if (_loc_4 == 0)
            {
                _loc_4 = 1;
            }// end if
            this.disposals.push(_loc_4);
            _loc_5 = (_loc_3 & 1) != 0;
            _loc_6 = (_loc_3 & 64) != 0;
            _loc_7 = Math.max(param1.readUnsignedShort() * 10, 10);
            this.delays.push(_loc_7);
            transIndex = param1.readUnsignedByte();
            if (this.gct != null && _loc_5 && transIndex != -1)
            {
                this.transparentColors.push(this.gct[transIndex]);
            }
            else
            {
                this.transparentColors.push(-1);
            }// end else if
            param1.readByte();
            _loc_8 = param1.position;
            _loc_9 = new ByteArray();
            param1.position = _loc_2;
            param1.readBytes(_loc_9, 0, _loc_8 - _loc_2);
            return _loc_9;
        }

        private function readHeader(param1:ByteArray) : ByteArray
        {
            var _loc_2:Number;
            var _loc_3:Number;
            var _loc_4:ByteArray;
            _loc_2 = 0;
            readMagicString(param1);
            readLSD(param1);
            if (gctFlag)
            {
                gct = readColorTable(gctSize, param1);
                this.bgColor = gct[bgIndex];
            }// end if
            _loc_3 = param1.position;
            _loc_4 = new ByteArray();
            param1.position = _loc_2;
            param1.readBytes(_loc_4, 0, _loc_3 - _loc_2);
            return _loc_4;
        }

        private function readLSD(param1:ByteArray) : void
        {
            var _loc_2:int;
            var _loc_3:int;
            width = param1.readUnsignedShort();
            height = param1.readUnsignedShort();
            _loc_2 = param1.readByte();
            this.gctFlag = (_loc_2 & 128) != 0;
            this.gctSize = 2 << (_loc_2 & 7);
            this.bgIndex = param1.readByte();
            _loc_3 = param1.readByte();
            return;
        }

        public function get isGif() : Boolean
        {
            return _isGif;
        }

        public function parse() : void
        {
            if (bytes != null)
            {
                this.header = readHeader(this.bytes);
                readContents(this.bytes);
            }// end if
            if (graphicsByteArrays.length == imageByteArrays.length + 1)
            {
                graphicsByteArrays.shift();
                transparentColors.shift();
                delays.shift();
                disposals.shift();
            }// end if
            bytes = null;
            return;
        }

        private function makeImageData(param1:ByteArray, param2:ByteArray) : ByteArray
        {
            var _loc_3:ByteArray;
            _loc_3 = new ByteArray();
            _loc_3.writeBytes(this.header);
            _loc_3.writeByte(33);
            _loc_3.writeByte(249);
            if (param2 != null)
            {
                _loc_3.writeBytes(param2);
            }// end if
            _loc_3.writeByte(44);
            _loc_3.writeBytes(param1);
            _loc_3.writeByte(59);
            return _loc_3;
        }

        private function readContents(param1:ByteArray) : void
        {
            var _loc_2:Boolean;
            var _loc_3:Number;
            var _loc_4:int;
            var _loc_5:int;
            var _loc_6:int;
            var _loc_7:int;
            var _loc_8:int;
            _loc_2 = false;
            while (!_loc_2 && param1.position < param1.length)
            {
                // label
                _loc_3 = param1.readByte();
                switch(_loc_3)
                {
                    case 44:
                    {
                        imageByteArrays.push(readImage(param1));
                        break;
                    }
                    case 33:
                    {
                        _loc_4 = param1.readUnsignedByte();
                        _loc_5 = 255;
                        _loc_6 = 249;
                        _loc_7 = 1;
                        _loc_8 = 254;
                        switch(_loc_4)
                        {
                            case _loc_6:
                            {
                                graphicsByteArrays.push(readGraphicControlExt(param1));
                                break;
                            }
                            case _loc_5:
                            {
                                applicationExtension = readUntilTerminator(param1);
                                break;
                            }
                            case _loc_7:
                            {
                                readUntilTerminator(param1);
                                break;
                            }
                            case _loc_8:
                            {
                                comments.push(readUntilTerminator(param1).toString());
                                break;
                            }
                            default:
                            {
                                readUntilTerminator(param1);
                                break;
                            }
                        }
                        break;
                    }
                    case 59:
                    {
                        _loc_2 = true;
                        break;
                    }
                    case 0:
                    {
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }
            return;
        }

        private function readColorTable(param1:int, param2:ByteArray) : Array
        {
            var _loc_3:int;
            var _loc_4:ByteArray;
            var _loc_5:Array;
            var _loc_6:int;
            var _loc_7:int;
            var _loc_8:int;
            var _loc_9:int;
            var _loc_10:int;
            var _loc_11:int;
            _loc_3 = 3 * param1;
            _loc_4 = new ByteArray();
            param2.readBytes(_loc_4, 0, _loc_3);
            _loc_5 = new Array();
            _loc_6 = 0;
            _loc_5 = new Array(256);
            _loc_7 = 0;
            _loc_8 = 0;
            while (_loc_7 < param1)
            {
                // label
                _loc_9 = _loc_4[_loc_8++] as int & 255;
                _loc_10 = _loc_4[_loc_8++] as int & 255;
                _loc_11 = _loc_4[_loc_8++] as int & 255;
                _loc_5[++_loc_7] = _loc_9 << 16 ^ _loc_10 << 8 ^ _loc_11;
            }
            return _loc_5;
        }

        private function readImage(param1:ByteArray) : ByteArray
        {
            var _loc_2:Number;
            var _loc_3:int;
            var _loc_4:int;
            var _loc_5:int;
            var _loc_6:int;
            var _loc_7:Rectangle;
            var _loc_8:int;
            var _loc_9:int;
            var _loc_10:Boolean;
            var _loc_11:Number;
            var _loc_12:ByteArray;
            _loc_2 = param1.position;
            _loc_3 = param1.readUnsignedShort();
            _loc_4 = param1.readUnsignedShort();
            _loc_5 = param1.readUnsignedShort();
            _loc_6 = param1.readUnsignedShort();
            if (_loc_5 > width)
            {
                width = _loc_5;
            }// end if
            if (_loc_6 > height)
            {
                height = _loc_6;
            }// end if
            _loc_7 = new Rectangle(_loc_3, _loc_4, _loc_5, _loc_6);
            rectBounds.push(_loc_7);
            _loc_8 = param1.readByte();
            lctFlag = (_loc_8 & 128) != 0;
            interlace = (_loc_8 & 64) != 0;
            lctSize = 2 << (_loc_8 & 7);
            if (lctFlag)
            {
                lct = readColorTable(lctSize, param1);
                act = lct;
            }
            else
            {
                act = gct;
                if (bgIndex == transIndex)
                {
                    bgColor = 0;
                }// end if
            }// end else if
            _loc_9 = 0;
            if (transparency)
            {
                _loc_9 = act[transIndex];
                act[transIndex] = 0;
            }// end if
            param1.readByte();
            _loc_10 = false;
            readUntilTerminator(param1);
            _loc_11 = param1.position;
            _loc_12 = new ByteArray();
            param1.position = _loc_2;
            param1.readBytes(_loc_12, 0, _loc_11 - _loc_2);
            return _loc_12;
        }

        private function readUntilTerminator(param1:ByteArray) : ByteArray
        {
            var _loc_2:Number;
            var _loc_3:Boolean;
            var _loc_4:Number;
            var _loc_5:ByteArray;
            var _loc_6:int;
            var _loc_7:ByteArray;
            _loc_2 = param1.position;
            _loc_3 = false;
            while (!_loc_3)
            {
                // label
                _loc_6 = param1[param1.position];
                if (_loc_6 == 0)
                {
                    param1.readByte();
                    _loc_3 = true;
                    continue;
                }// end if
                _loc_7 = readBlock(param1);
            }
            _loc_4 = param1.position;
            _loc_5 = new ByteArray();
            param1.position = _loc_2;
            param1.readBytes(_loc_5, 0, _loc_4 - _loc_2);
            return _loc_5;
        }
    }
}
